#include "Manager.h"
namespace SLG
{
	ModelManager::ModelManager(void)
		:Manager("ModelManager")
	{
	}

	ModelManager::~ModelManager(void)
	{
		Log();
	}
	FigureManager::FigureManager(void)
		:Manager("FigureManager")
	{
	}

	FigureManager::~FigureManager(void)
	{
		Log();
	}
	TextureManager::TextureManager(void)
		:Manager("TextureManager")
	{
	}

	TextureManager::~TextureManager(void)
	{
		Log();
	}

	AnimManager::AnimManager(ModelManager* mm,FigureManager* fm)
		:Manager("AnimManager"),
		m_mManager(mm),
		m_fManager(fm)
	{
	}

	AnimManager::~AnimManager(void)
	{
		Log();
	}

	bool ModelManager::AddObj(int32 mid, int32 tid,char *name, void* data)
	{
		assert(mid&&name);
		if(HasObj(mid)>=0)
			return false;
		OBJ o;
		o.mid=mid;
		o.tid=tid;
		size_t size=strlen(name);
		o.name=new char[size+1];
		strcpy_s(o.name,size+1,name);
		o.model=(Model*)data;
		o.id=m_cur++;
		m_data.push_back(o);
		return true;
	}

	Model* ModelManager::GetModel(int32 id)
	{
		if(m_data.size()>id)
			return m_data[id].model;
		return NULL;
	}

	void ModelManager::Log()
	{
		_log("Model:\n");
		for(vector<OBJ>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			char tmp[256];
			sprintf(tmp,"id:%d\n",iter->id);
			_log(tmp);
			sprintf(tmp,"model name:%s\n",iter->name);
			_log(tmp);
		}
	}

	int32 ModelManager::HasObj(int32 id)
	{
		for(vector<OBJ>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			if(iter->mid==id)
				return iter->id;
		}
		return -1;
	}

	int32 FigureManager::HasObj(int32 fid)
	{
		for(vector<FIGURE>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			if(iter->fid==fid)
			{
				return iter->id;
			}
		}
		return -1;
	}

	int32 FigureManager::GetFidFromCell(int32 x,int32 y)
	{
		for(vector<FIGURE>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			if(iter->cell_x==x&&iter->cell_y==y)
			{
				return iter->id;
			}
		}
		return -1;
	}

	D3DXVECTOR3 FigureManager::GetMidPos(int32 fid)
	{
		if(m_data.size()<=fid)
			return D3DXVECTOR3(0,0,0);
		return m_data[fid].aabb->m_center;
	}
	
	int32 TextureManager::HasObj(char*name)
	{
		for(vector<TEXTURE>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			if(strcmp(iter->name,name)==0)
			{
				return iter->id;
			}
		}
		return -1;
	}
	

	bool FigureManager::AddObj(int32 fid,int32 mid,const char* name,int32 x,int32 y,FACE f)
	{
		if(HasObj(fid)>=0)
			return false;
		FIGURE tmp;
		tmp.id=m_cur++;
		tmp.fid=fid;
		tmp.mid=mid;
		tmp.aabb=NULL;
		size_t size=strlen(name);
		tmp.name=new char[size+1];
		strcpy_s(tmp.name,size+1,name);
		tmp.cell_x=x;
		tmp.cell_y=y;
		tmp.face=f;
		tmp.nVB=0;
		m_data.push_back(tmp);
		return true;
	}

	void FigureManager::Log()
	{
		_log("Figure:\n");
		for(vector<FIGURE>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			char tmp[256];
			sprintf(tmp,"id:%d\tmodel id:%d\tfigure name:%s\tpos x:%f y:%f\t\tface:%d\n",
				iter->id,iter->mid,iter->name,iter->cell_x,iter->cell_y,iter->face);
			_log(tmp);
		}
	}

	int32 FigureManager::GetMid(int32 id)
	{
		/*for(vector<FIGURE>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			if(iter->id==fid)
			{
				return iter->mid;
			}
		}
		return -1;*/
		if(m_data.size()>id)
			return m_data[id].mid;
		return -1;
	}

	bool FigureManager::AddVB(int32 id,LPDIRECT3DVERTEXBUFFER9 vb,int32 count)
	{
		/*for(vector<FIGURE>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			if(iter->id==id)
			{
				iter->VB[iter->nVB].pVB=vb;
				iter->VB[iter->nVB].count=count;
				iter->nVB++;
				return true;
			}
		}
		return false;*/
		if(m_data.size()>id)
		{
			m_data[id].VB[m_data[id].nVB].pVB=vb;
			m_data[id].VB[m_data[id].nVB].count=count;
			m_data[id].nVB++;
			return true;
		}
		return false;
	}

	int32 TextureManager::AddObj(char* name,LPDIRECT3DTEXTURE9 tex)
	{
		int32 id;
		if((id=HasObj(name))>=0)
		{
			return id;
		}
		TEXTURE tmp;
		tmp.id=m_cur++;
		size_t size=strlen(name);
		tmp.name=new char[size+1];
		strcpy_s(tmp.name,size+1,name);
		tmp.tex=tex;
		m_data.push_back(tmp);
		return tmp.id;
	}

	void TextureManager::Log()
	{
		_log("Texture:\n");
		for(vector<TEXTURE>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			char tmp[1024];
			sprintf(tmp,"id:%d\ttexture name:%s\ttex:\n",
				iter->id,iter->name,iter->tex);
			_log(tmp);
		}
	}

	bool AnimManager::AddObj(int32 fid,char* name,int32 anim)
	{
		ANIMATION tmp;
		tmp.id=m_cur++;
		tmp.fid=fid;
		size_t size=strlen(name);
		tmp.name=new char[size+1];
		strcpy_s(tmp.name,size+1,name);
		tmp.anim=anim;
		tmp.vertices=NULL;
		m_data.push_back(tmp);
		ChangeAnim(fid,anim);
		return true;
	}

	void AnimManager::Log()
	{
	}

	bool FigureManager::ClearVB()
	{
		for(vector<FIGURE>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			for(int i=0;i<iter->nVB;i++)
			{
				iter->VB[i].count=0;
				iter->VB[i].pVB->Release();
			}
			iter->nVB=0;
		}
		return true;
	}

	void AnimManager::CalcAnim(DWORD time)
	{
		if(m_data.empty())
			return;
		for(vector<ANIMATION>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			int32 mid=m_fManager->GetMid(iter->fid);
			assert(mid!=-1);
			if(iter->vertices!=NULL)
				delete iter->vertices;
			AnimatePreModel(m_mManager->GetModel(mid),iter->anim,&iter->vertices,time);
		}
	}

	void AnimManager::AnimatePreModel(Model* m,size_t anim,D3DXVECTOR3** veritces,DWORD time)
	{
		ModelAnimation* anims=m->anims;
		Bone* bones=m->bones;



		ModelAnimation &a = anims[anim];
		int tmax = (a.timeEnd-a.timeStart);
		if (tmax==0) 
			tmax = 1;

		size_t t=time;
		t %= tmax;
		t += a.timeStart;
		//t = animManager->GetFrame();

		/*if(t>=anims[anim].timeEnd)
		{
			t=anims[anim].timeStart;
		}*/

		m->animtime=t;
		//animtime=t;
		CalcBones(m,anim, t);

		t+=(anims[anim].timeEnd-anims[anim].timeStart)/1000;

		// transform vertices
		ModelVertex *ov = m->vertices;
		*veritces=new D3DXVECTOR3[m->header->nVertices];
		for (size_t i=0; i<m->header->nVertices; ++i,++ov) 
		{ //,k=0
			D3DXVECTOR3 v(0,0,0), n(0,0,0);

			for (size_t b=0; b<4; b++)
			{
				if (ov->weights[b]>0) 
				{
					D3DXVECTOR3 tv ;
					D3DXVec3TransformCoord(&tv , &ov->pos,&bones[ov->bones[b]].mat);
					v += tv * ((float)ov->weights[b] / 255.0f);
				}
			}
			(*veritces)[i] = v;
		}
	}

	void AnimManager::CalcBones(Model* m,size_t anim, size_t time)
	{
		Bone* bones=m->bones;
		for (size_t i=0; i<m->header->nBones; i++) {
			bones[i].calc = false;
		}

		for (size_t i=0; i<m->header->nBones; i++) {
			bones[i].calcMatrix(bones, anim, time,true);
		}
	}

	bool AnimManager::ChangeAnim(int32 fid, int32 anim)
	{
		for(vector<ANIMATION>::iterator iter=m_data.begin();iter<m_data.end();iter++)
		{
			if(iter->id==fid)
			{
				iter->anim=anim;
				Model* m=m_mManager->GetModel(m_fManager->GetMid(fid));
			}
		}
		return false;
	}
}